﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using Community.CsharpSqlite.Entity;

namespace Community.CsharpSqlite
{
    public  class Utility
    {





        /*
    ** The database page the Global.PENDING_BYTE occupies. This page is never used.
    */
        //# define PENDING_BYTE_PAGE(pBt) PAGER_MJ_PGNO(pBt)
        // TODO -- Convert PENDING_BYTE_PAGE to inline
        public static uint PENDING_BYTE_PAGE(BtShared pBt)
        {
            return PAGER_MJ_PGNO(pBt.pPager);
        }

        /*
** Page number PAGER_MJ_PGNO is never used in an SQLite database (it is
** reserved for working around a windows/posix incompatibility). It is
** used in the journal to signify that the remainder of the journal file
** is devoted to storing a master journal name - there are no more pages to
** roll back. See comments for function writeMasterJournal() in pager.c
** for details.
*/
        //#define PAGER_MJ_PGNO(x) ((uint)((Global.PENDING_BYTE/((x)->pageSize))+1))
        public static uint PAGER_MJ_PGNO(Pager x)
        {
            return ((uint)((Global.PENDING_BYTE / ((x).pageSize)) + 1));
        }

        /*
** The following macro converts a relative address in the p2 field
** of a VdbeOp structure into a negative number so that
** VdbeAux.VdbeAddOpList() knows that the address is relative.  Calling
** the macro again restores the address.
*/
        //#define Addr(X)  (-1-(X))
        public static int Addr(int x)
        {
            return -1 - x;
        }


        /*
** The macro Unlikely() is a hint that surrounds a boolean
** expression that is usually false.  Macro Likely() surrounds
** a boolean expression that is usually true.  GCC is able to
** use these hints to generate better code, sometimes.
*/
#if (__GNUC__) && FALSE
//# define Likely(X)    __builtin_expect((X),1)
//# define Unlikely(X)  __builtin_expect((X),0)
#else
        //# define Likely(X)    !!(X)
        public static bool Likely(bool X)
        {
            return !!X;
        }

        //# define Unlikely(X)  !!(X)
        public static bool Unlikely(bool X)
        {
            return !!X;
        }
#endif

        /*
    ** Test to see whether or not a table is a virtual table.  This is
    ** done as a macro so that it will be optimized out when virtual
    ** table support is omitted from the build.
    */
#if !SQLITE_OMIT_VIRTUALTABLE
//#  define IsVirtual(X)      (((X)->tabFlags & TabFlag.TF_Virtual)!=0)
static bool IsVirtual( Table X) { return (X.tabFlags & TabFlag.TF_Virtual)!=0;}
//#  define IsHiddenColumn(X) ((X)->isHidden)
static bool IsVirtual( Column X) { return X.isHidden!=0;}
#else
        //#  define IsVirtual(X)      0
        public static bool IsVirtual(Table T)
        {
            return false;
        }

        //#  define IsHiddenColumn(X) 0
        public static bool IsHiddenColumn(Column C)
        {
            return false;
        }
#endif


        /// <summary>
        ///  Return a static string that describes the kind of error specified in the
        ///  argument.
        /// </summary>
        public static string ErrorString(int rc)
        {
            var aMsg = new[]
                           {
/* StatusCode.SQLITE_OK          */ "not an error",
/* StatusCode.SQLITE_ERROR       */ "SQL logic error or missing database",
/* StatusCode.SQLITE_INTERNAL    */ "",
/* StatusCode.SQLITE_PERM        */ "access permission denied",
/* StatusCode.SQLITE_ABORT       */ "callback requested query abort",
/* StatusCode.SQLITE_BUSY        */ "database is locked",
/* StatusCode.SQLITE_LOCKED      */ "database table is locked",
/* StatusCode.SQLITE_NOMEM       */ "out of memory",
/* StatusCode.SQLITE_READONLY    */ "attempt to write a readonly database",
/* StatusCode.SQLITE_INTERRUPT   */ "interrupted",
/* StatusCode.SQLITE_IOERR       */ "disk I/O error",
/* StatusCode.SQLITE_CORRUPT     */ "database disk image is malformed",
/* StatusCode.SQLITE_NOTFOUND    */ "",
/* StatusCode.SQLITE_FULL        */ "database or disk is full",
/* StatusCode.SQLITE_CANTOPEN    */ "unable to open database file",
/* StatusCode.SQLITE_PROTOCOL    */ "",
/* StatusCode.SQLITE_EMPTY       */ "table contains no data",
/* StatusCode.SQLITE_SCHEMA      */ "database schema has changed",
/* StatusCode.SQLITE_TOOBIG      */ "string or blob too big",
/* StatusCode.SQLITE_CONSTRAINT  */ "constraint failed",
/* StatusCode.SQLITE_MISMATCH    */ "datatype mismatch",
/* StatusCode.SQLITE_MISUSE      */ "library routine called out of sequence",
/* StatusCode.SQLITE_NOLFS       */ "large file support is disabled",
/* StatusCode.SQLITE_AUTH        */ "authorization denied",
/* StatusCode.SQLITE_FORMAT      */ "auxiliary database format error",
/* StatusCode.SQLITE_RANGE       */ "bind or column index out of range",
/* StatusCode.SQLITE_NOTADB      */ "file is encrypted or is not a database",
                           };
            rc &= 0xff;
            if (UnitTest.ALWAYS(rc >= 0) && rc < aMsg.Length && aMsg[rc] != "") //(int)(sizeof(aMsg)/sizeof(aMsg[0]))
            {
                return aMsg[rc];
            }
            else
            {
                return "unknown error";
            }
        }
        /*
    ** Round up a number to the next larger multiple of 8.  This is used
    ** to force 8-byte alignment on 64-bit architectures.
    */
        //#define ROUND8(x)     (((x)+7)&~7)
        public static int ROUND8(int x)
        {
            return (x + 7) & ~7;
        }

        /*
    ** Round down to the nearest multiple of 8
    */
        //#define ROUNDDOWN8(x) ((x)&~7)
        public static int ROUNDDOWN8(int x)
        {
            return x & ~7;
        }


        /*
    ** A convenience macro that returns the number of elements in
    ** an array.
    */
        //#define ArraySize(X)    ((int)(sizeof(X)/sizeof(X[0])))
        public static int ArraySize<T>(T[] x)
        {
            return x.Length;
        }



        /*
    ** 2001 September 15
    **
    ** The author disclaims copyright to this source code.  In place of
    ** a legal notice, here is a blessing:
    **
    **    May you do good and not evil.
    **    May you find forgiveness for yourself and forgive others.
    **    May you share freely, never taking more than you give.
    **
    *************************************************************************
    ** Utility functions used throughout sqlite.
    **
    ** This file contains functions for allocating memory, comparing
    ** strings, and stuff like that.
    **
    *************************************************************************
    **  Included in SQLite3 port to C#-SQLite;  2008 Noah B Hart
    **  C#-SQLite is an independent reimplementation of the SQLite software library
    **
    **  SQLITE_SOURCE_ID: 2010-03-09 19:31:43 4ae453ea7be69018d8c16eb8dabe05617397dc4d
    **
    **  $Header: Community.CsharpSqlite/src/util_c.cs,v 6604176a7dbe 2010/03/12 23:35:36 Noah $
    *************************************************************************
    */
        //#include "sqliteInt.h"
        //#include <stdarg.h>
#if SQLITE_HAVE_ISNAN
//# include <math.h>
#endif


        /*
** Routine needed to support the UnitTest.TestCase() macro.
*/
#if SQLITE_COVERAGE_TEST
void sqlite3Coverage(int x){
static int dummy = 0;
dummy += x;
}
#endif

#if !SQLITE_OMIT_FLOATING_POINT
        /*
** Return true if the floating point value is Not a Number (NaN).
**
** Use the math library isnan() function if compiled with SQLITE_HAVE_ISNAN.
** Otherwise, we have our own implementation that works on most systems.
*/

        public static bool Sqlite3IsNaN(double x)
        {
            bool rc; /* The value return */
#if !(SQLITE_HAVE_ISNAN)
            /*
** Systems that support the isnan() library function should probably
** make use of it by compiling with -DSQLITE_HAVE_ISNAN.  But we have
** found that many systems do not have a working isnan() function so
** this implementation is provided as an alternative.
**
** This NaN test sometimes fails if compiled on GCC with -ffast-math.
** On the other hand, the use of -ffast-math comes with the following
** warning:
**
**      This option [-ffast-math] should never be turned on by any
**      -O option since it can result in incorrect output for programs
**      which depend on an exact implementation of IEEE or ISO
**      rules/specifications for math functions.
**
** Under MSVC, this NaN test may fail if compiled with a floating-
** point precision mode other than /fp:precise.  From the MSDN
** documentation:
**
**      The compiler [with /fp:precise] will properly handle comparisons
**      involving NaN. For example, x != x evaluates to true if x is NaN
**      ...
*/
#if __FAST_MATH__
# error SQLite will not work correctly with the -ffast-math option of GCC.
#endif
            double y = x;
            double z = y;
            rc = (y != z);
#else //* if defined(SQLITE_HAVE_ISNAN) */
rc = isnan(x);
#endif
            //* SQLITE_HAVE_ISNAN */
            UnitTest.TestCase(rc);
            return rc;
        }
#endif
        //* SQLITE_OMIT_FLOATING_POINT */

        /*
** Compute a string length that is limited to what can be stored in
** lower 30 bits of a 32-bit signed integer.
**
** The value returned will never be negative.  Nor will it ever be greater
** than the actual length of the string.  For very long strings (greater
** than 1GiB) the value returned might be less than the true string length.
*/

        public static int Sqlite3Strlen30(int z)
        {
            return 0x3fffffff & z;
        }

        public static int Sqlite3Strlen30(StringBuilder z)
        {
            //const char *z2 = z;
            if (z == null) return 0;
            //while( *z2 ){ z2++; }
            //return 0x3fffffff & (int)(z2 - z);
            return 0x3fffffff & z.Length;
        }

        public static int Sqlite3Strlen30(string z)
        {
            //const char *z2 = z;
            if (z == null) return 0;
            //while( *z2 ){ z2++; }
            //return 0x3fffffff & (int)(z2 - z);
            return 0x3fffffff & z.Length;
        }


        /*
    ** Set the most recent error code and error string for the sqlite
    ** handle "db". The error code is set to "err_code".
    **
    ** If it is not NULL, string zFormat specifies the format of the
    ** error string in the style of the Custom.Printf functions: The following
    ** format characters are allowed:
    **
    **      %s      Insert a string
    **      %z      A string that should be freed after use
    **      %d      Insert an integer
    **      %T      Insert a token
    **      %S      Insert the first element of a SrcList
    **
    ** zFormat and any string tokens that follow it are assumed to be
    ** encoded in UTF-8.
    **
    ** To clear the most recent error for sqlite handle "db", Sqlite3Error
    ** should be called with err_code set to StatusCode.SQLITE_OK and zFormat set
    ** to NULL.
    */
        //Overloads
        public static void Sqlite3Error(sqlite3 db, int err_code, int noString)
        {
            Sqlite3Error(db, err_code, err_code == 0 ? null : "");
        }

        public static void Sqlite3Error(sqlite3 db, int err_code, string zFormat, params object[] ap)
        {
            if (db != null && (db.pErr != null || (db.pErr = Sqlite3.sqlite3ValueNew(db)) != null))
            {
                db.errCode = err_code;
                if (zFormat != null)
                {
                    string z;
                    Custom.VaStart(ap, zFormat);
                    z = Print.VMPrintf(db, zFormat, ap);
                    Custom.VaEnd(ap);
                    Sqlite3.sqlite3ValueSetStr(db.pErr, -1, z, Const.SQLITE_UTF8, Const.SQLITE_DYNAMIC);
                }
                else
                {
                    Sqlite3.sqlite3ValueSetStr(db.pErr, 0, null, Const.SQLITE_UTF8, Const.SQLITE_STATIC);
                }
            }
        }

        /*
    ** Add an error message to pParse.zErrMsg and increment pParse.nErr.
    ** The following formatting characters are allowed:
    **
    **      %s      Insert a string
    **      %z      A string that should be freed after use
    **      %d      Insert an integer
    **      %T      Insert a token
    **      %S      Insert the first element of a SrcList
    **
    ** This function should be used to report any error that occurs whilst
    ** compiling an SQL statement (i.e. within sqlite3_prepare()). The
    ** last thing the sqlite3_prepare() function does is copy the error
    ** stored by this function into the database handle using Sqlite3Error().
    ** Function Sqlite3Error() should be used during statement execution
    ** (sqlite3_step() etc.).
    */

        public static void Sqlite3ErrorMsg(Parse pParse, string zFormat, params object[] ap)
        {
            string zMsg;
            //va_list ap;
            sqlite3 db = pParse.db;
            Custom.VaStart(ap, zFormat);
            zMsg = Print.VMPrintf(db, zFormat, ap);
            Custom.VaEnd(ap);
            if (db.suppressErr != 0)
            {
               MemPool.DbFree(db, ref zMsg);
            }
            else
            {
                pParse.nErr++;
                MemPool.DbFree(db, ref pParse.zErrMsg);
                pParse.zErrMsg = zMsg;
                pParse.rc = StatusCode.SQLITE_ERROR;
            }
        }

      

        /*
    ** Convert an SQL-style quoted string into a normal string by removing
    ** the quote characters.  The conversion is done in-place.  If the
    ** input does not begin with a quote character, then this routine
    ** is a no-op.
    **
    ** The input string must be zero-terminated.  A new zero-terminator
    ** is added to the dequoted string.
    **
    ** The return value is -1 if no dequoting occurs or the length of the
    ** dequoted string, exclusive of the zero terminator, if dequoting does
    ** occur.
    **
    ** 2002-Feb-14: This routine is extended to remove MS-Access style
    ** brackets from around identifers.  For example:  "[a-b-c]" becomes
    ** "a-b-c".
    */

        public static int Sqlite3Dequote(ref string z)
        {
            char quote;
            int i;
            if (z == null || z == "") return -1;
            quote = z[0];
            switch (quote)
            {
                case '\'':
                    break;
                case '"':
                    break;
                case '`':
                    break; /* For MySQL compatibility */
                case '[':
                    quote = ']';
                    break; /* For MS SqlServer compatibility */
                default:
                    return -1;
            }
            var sbZ = new StringBuilder(z.Length);
            for (i = 1; i < z.Length; i++) //z[i] != 0; i++)
            {
                if (z[i] == quote)
                {
                    if (i < z.Length - 1 && (z[i + 1] == quote))
                    {
                        sbZ.Append(quote);
                        i++;
                    }
                    else
                    {
                        break;
                    }
                }
                else
                {
                    sbZ.Append(z[i]);
                }
            }
            z = sbZ.ToString();
            return sbZ.Length;
        }

     

        /*
    ** Some systems have stricmp().  Others have strcasecmp().  Because
    ** there is no consistency, we will define our own.
    */

        public static int Sqlite3StrICmp(string zLeft, string zRight)
        {
            //register unsigned char *a, *b;
            //a = (unsigned char *)zLeft;
            //b = (unsigned char *)zRight;
            //while( *a!=0 && Global.UpperToLower[*a]==Global.UpperToLower[*b]){ a++; b++; }
            //return Global.UpperToLower[*a] - Global.UpperToLower[*b];
            int a = 0, b = 0;
            if (zRight == null) return 0;
            while (a < zLeft.Length && b < zRight.Length && Global.UpperToLower[zLeft[a]] == Global.UpperToLower[zRight[b]])
            {
                a++;
                b++;
            }
            if (a == zLeft.Length && b == zRight.Length) return 0;
            else
            {
                if (a == zLeft.Length) return -Global.UpperToLower[zRight[b]];
                if (b == zRight.Length) return Global.UpperToLower[zLeft[a]];
                return Global.UpperToLower[zLeft[a]] - Global.UpperToLower[zRight[b]];
            }
        }

        //public static int sqlite3_strnicmp(string zLeft, int offsetLeft, string zRight, int N)
        //{
        //    return Sqlite3StrNICmp(zLeft, offsetLeft, zRight, N);
        //}

        public static int Sqlite3StrNICmp(string zLeft, int offsetLeft, string zRight, int N)
        {
            //register unsigned char *a, *b;
            //a = (unsigned char *)zLeft;
            //b = (unsigned char *)zRight;
            int a = 0, b = 0;
            while (N-- > 0 && a < zLeft.Length - offsetLeft && b < zRight.Length && zLeft[a + offsetLeft] != 0 &&
                   Global.UpperToLower[zLeft[a + offsetLeft]] == Global.UpperToLower[zRight[b]])
            {
                a++;
                b++;
            }
            return N < 0
                       ? 0
                       : ((a < zLeft.Length - offsetLeft) ? Global.UpperToLower[zLeft[a + offsetLeft]] : 0) -
                         Global.UpperToLower[zRight[b]];
        }

        public static int Sqlite3StrNICmp(string zLeft, string zRight, int N)
        {
            //register unsigned char *a, *b;
            //a = (unsigned char *)zLeft;
            //b = (unsigned char *)zRight;
            int a = 0, b = 0;
            while (N-- > 0 && a < zLeft.Length && b < zRight.Length &&
                   (zLeft[a] == zRight[b] ||
                    (zLeft[a] != 0 && zLeft[a] < 256 && zRight[b] < 256 &&
                     Global.UpperToLower[zLeft[a]] == Global.UpperToLower[zRight[b]])))
            {
                a++;
                b++;
            }
            if (N < 0) return 0;
            if (a == zLeft.Length && b == zRight.Length) return 0;
            if (a == zLeft.Length) return -Global.UpperToLower[zRight[b]];
            if (b == zRight.Length) return Global.UpperToLower[zLeft[a]];
            return (zLeft[a] < 256 ? Global.UpperToLower[zLeft[a]] : zLeft[a]) -
                   (zRight[b] < 256 ? Global.UpperToLower[zRight[b]] : zRight[b]);
        }

        /*
    ** Return TRUE if z is a pure numeric string.  Return FALSE and leave
    ** *realnum unchanged if the string contains any character which is not
    ** part of a number.
    **
    ** If the string is pure numeric, set *realnum to TRUE if the string
    ** contains the '.' character or an "E+000" style exponentiation suffix.
    ** Otherwise set *realnum to FALSE.  Note that just becaue *realnum is
    ** false does not mean that the number can be successfully converted into
    ** an integer - it might be too big.
    **
    ** An empty string is considered non-numeric.
    */

        public static int Sqlite3IsNumber(string z, ref int realnum, int enc)
        {
            if (String.IsNullOrEmpty(z)) return 0;
            int incr = (enc == Const.SQLITE_UTF8 ? 1 : 2);
            int zIndex = 0;
            if (enc == Const.SQLITE_UTF16BE) zIndex++; // z++;
            if (z[zIndex] == '-' || z[zIndex] == '+') zIndex += incr; //z += incr;
            if (zIndex == z.Length || !SqliteInt.Sqlite3Isdigit(z[zIndex]))
            {
                return 0;
            }
            zIndex += incr; //z += incr;
            realnum = 0;
            while (zIndex < z.Length && SqliteInt.Sqlite3Isdigit(z[zIndex]))
            {
                zIndex += incr;
            } //z += incr; }
#if !SQLITE_OMIT_FLOATING_POINT
            if (zIndex < z.Length && z[zIndex] == '.')
            {
                zIndex += incr; //z += incr;
                if (!SqliteInt.Sqlite3Isdigit(z[zIndex])) return 0;
                while (zIndex < z.Length && SqliteInt.Sqlite3Isdigit(z[zIndex]))
                {
                    zIndex += incr;
                } //z += incr; }
                realnum = 1;
            }
            if (zIndex < z.Length && (z[zIndex] == 'e' || z[zIndex] == 'E'))
            {
                zIndex += incr; //z += incr;
                if (zIndex < z.Length && (z[zIndex] == '+' || z[zIndex] == '-')) zIndex += incr; //z += incr;
                if (zIndex == z.Length || !SqliteInt.Sqlite3Isdigit(z[zIndex])) return 0;
                while (zIndex < z.Length && SqliteInt.Sqlite3Isdigit(z[zIndex]))
                {
                    zIndex += incr;
                } //z += incr; }
                realnum = 1;
            }
#endif
            return zIndex == z.Length ? 1 : 0; // z[zIndex] == 0;
        }

        /*
    ** The string z[] is an ASCII representation of a real number.
    ** Convert this string to a double.
    **
    ** This routine assumes that z[] really is a valid number.  If it
    ** is not, the result is undefined.
    **
    ** This routine is used instead of the library atof() function because
    ** the library atof() might want to use "," as the decimal point instead
    ** of "." depending on how locale is set.  But that would cause problems
    ** for SQL.  So this routine always uses "." regardless of locale.
    */

        public static int Sqlite3AtoF(string z, ref double pResult)
        {
#if !SQLITE_OMIT_FLOATING_POINT
            if (String.IsNullOrEmpty(z))
            {
                pResult = 0;
                return 0;
            }
            z = z.Trim() + " "; //const char *zBegin = z;

            /* sign * significand * (10 ^ (esign * exponent)) */
            int sign = 1; /* sign of significand */
            long s = 0; /* significand */
            int d = 0; /* adjust exponent for shifting decimal point */
            int esign = 1; /* sign of exponent */
            int e = 0; /* exponent */
            double result = 0;
            int nDigits = 0;

            int zDx = 0;
            while (SqliteInt.Sqlite3Isspace(z[zDx])) zDx++;
            /* get sign of significand */
            if (z[zDx] == '-')
            {
                sign = -1;
                zDx++;
            }
            else if (z[zDx] == '+')
            {
                zDx++;
            }
            /* skip leading zeroes */
            while (z[zDx] == '0')
            {
                zDx++;
                nDigits++;
            }
            /* copy max significant digits to significand */
            while (SqliteInt.Sqlite3Isdigit(z[zDx]) && s < ((Const.LARGEST_INT64 - 9) / 10))
            {
                s = s * 10 + (z[zDx] - '0');
                zDx++;
                nDigits++;
            }
            /* skip non-significant significand digits
      ** (increase exponent by d to shift decimal left) */
            while (SqliteInt.Sqlite3Isdigit(z[zDx]))
            {
                zDx++;
                nDigits++;
                d++;
            }

            /* if decimal point is present */
            if (z[zDx] == '.')
            {
                zDx++;
                /* copy digits from after decimal to significand
        ** (decrease exponent by d to shift decimal right) */
                while (SqliteInt.Sqlite3Isdigit(z[zDx]) && s < ((Const.LARGEST_INT64 - 9) / 10))
                {
                    s = s * 10 + (z[zDx] - '0');
                    zDx++;
                    nDigits++;
                    d--;
                }
                /* skip non-significant digits */
                while (SqliteInt.Sqlite3Isdigit(z[zDx]))
                {
                    zDx++;
                    nDigits++;
                }
            }

            /* if exponent is present */
            if (z[zDx] == 'e' || z[zDx] == 'E')
            {
                zDx++;
                /* get sign of exponent */
                if (z[zDx] == '-')
                {
                    esign = -1;
                    zDx++;
                }
                else if (z[zDx] == '+')
                {
                    zDx++;
                }
                /* copy digits to exponent */
                while (SqliteInt.Sqlite3Isdigit(z[zDx]))
                {
                    e = e * 10 + (z[zDx] - '0');
                    zDx++;
                }
            }

            /* adjust exponent by d, and update sign */
            e = (e * esign) + d;
            if (e < 0)
            {
                esign = -1;
                e *= -1;
            }
            else
            {
                esign = 1;
            }

            /* if 0 significand */
            if (0 == s)
            {
                /* In the IEEE 754 standard, zero is signed.
        ** Add the sign if we've seen at least one digit */
                result = (sign < 0 && nDigits != 0) ? -(double)0 : 0;
            }
            else
            {
                /* attempt to reduce exponent */
                if (esign > 0)
                {
                    while (s < (Const.LARGEST_INT64 / 10) && e > 0)
                    {
                        e--;
                        s *= 10;
                    }
                }
                else
                {
                    while (0 == (s % 10) && e > 0)
                    {
                        e--;
                        s /= 10;
                    }
                }

                /* adjust the sign of significand */
                s = sign < 0 ? -s : s;

                /* if exponent, scale significand as appropriate
        ** and store in result. */
                if (e != 0)
                {
                    double scale = 1.0;
                    /* attempt to handle extremely small/large numbers better */
                    if (e > 307 && e < 342)
                    {
                        while ((e % 308) != 0)
                        {
                            scale *= 1.0e+1;
                            e -= 1;
                        }
                        if (esign < 0)
                        {
                            result = s / scale;
                            result /= 1.0e+308;
                        }
                        else
                        {
                            result = s * scale;
                            result *= 1.0e+308;
                        }
                    }
                    else
                    {
                        /* 1.0e+22 is the largest power of 10 than can be 
            ** represented exactly. */
                        while ((e % 22) != 0)
                        {
                            scale *= 1.0e+1;
                            e -= 1;
                        }
                        while (e > 0)
                        {
                            scale *= 1.0e+22;
                            e -= 22;
                        }
                        if (esign < 0)
                        {
                            result = s / scale;
                        }
                        else
                        {
                            result = s * scale;
                        }
                    }
                }
                else
                {
                    result = s;
                }
            }
            /* store the result */
            pResult = result;

            /* return number of characters used */
            return (zDx);
#else
return Sqlite3Atoi64(z, pResult);
#endif
            //* SQLITE_OMIT_FLOATING_POINT */
        }

        /*
    ** Compare the 19-character string zNum against the text representation
    ** value 2^63:  9223372036854775808.  Return negative, zero, or positive
    ** if zNum is less than, equal to, or greater than the string.
    **
    ** Unlike Custom.Memcmp() this routine is guaranteed to return the difference
    ** in the values of the last digit if the only difference is in the
    ** last digit.  So, for example,
    **
    **      Compare2pow63("9223372036854775800")
    **
    ** will return -8.
    */

        private static int Compare2pow63(string zNum)
        {
            int c;
            if (zNum.Length <= 18)
                c = string.Compare(zNum, "922337203685477580");
            else
            {
                c = (string.Compare(zNum.Substring(0, 18), "922337203685477580") == 1) ? 10 : 0;
                if (c == 0)
                {
                    c = zNum[18] - '8';
                    UnitTest.TestCase(c == (-1));
                    UnitTest.TestCase(c == 0);
                    UnitTest.TestCase(c == (+1));
                }
            }
            return c;
        }


        /*
    ** Return TRUE if zNum is a 64-bit signed integer and write
    ** the value of the integer into pNum.  If zNum is not an integer
    ** or is an integer that is too large to be expressed with 64 bits,
    ** then return false.
    **
    ** When this routine was originally written it dealt with only
    ** 32-bit numbers.  At that time, it was much faster than the
    ** Custom.Atoi() library routine in RedHat 7.2.
    */

        public static bool Sqlite3Atoi64(string zNum, ref long pNum)
        {
            zNum = zNum.Trim() + " ";
            int i;
            for (i = 1; i < zNum.Length; i++) if (!SqliteInt.Sqlite3Isdigit(zNum[i])) break;
            bool c = Int64.TryParse(zNum.Substring(0, i), out pNum);
            if (i < zNum.Length - 1) c = false;
            return c;
            //long v = 0;
            //int neg;
            //int i, c;
            //const char *zStart;
            //while( SqliteInt.Sqlite3Isspace(*(byte*)zNum) ) zNum++;
            //if( *zNum=='-' ){
            //  neg = 1;
            //  zNum++;
            //}else if( *zNum=='+' ){
            //  neg = 0;
            //  zNum++;
            //}else{
            //  neg = 0;
            //}
            //zStart = zNum;
            //while( zNum[0]=='0' ){ zNum++; } /* Skip over leading zeros. Ticket #2454 */
            //for(i=0; (c=zNum[i])>='0' && c<='9'; i++){
            //  v = v*10 + c - '0';
            //}
            //*pNum = neg ? -v : v;
            //UnitTest.TestCase(i == 18);
            //UnitTest.TestCase(i == 19);
            //UnitTest.TestCase(i == 20);
            //if( c!=0 || (i==0 && zStart==zNum) || i>19 ){
            //  /* zNum is empty or contains non-numeric text or is longer
            //  ** than 19 digits (thus guaranting that it is too large) */
            //  return 0;
            //}else if( i<19 ){
            //  /* Less than 19 digits, so we know that it fits in 64 bits */
            //  return 1;
            //}else{
            //  /* 19-digit numbers must be no larger than 9223372036854775807 if positive
            //  ** or 9223372036854775808 if negative.  Note that 9223372036854665808
            //  ** is 2^63. */
            //  return Compare2pow63(zNum)<neg;
            //}
        }

        /*
    ** The string zNum represents an unsigned integer.  The zNum string
    ** consists of one or more digit characters and is terminated by
    ** a zero character.  Any stray characters in zNum result in undefined
    ** behavior.
    **
    ** If the unsigned integer that zNum represents will fit in a
    ** 64-bit signed integer, return TRUE.  Otherwise return FALSE.
    **
    ** If the negFlag parameter is true, that means that zNum really represents
    ** a negative number.  (The leading "-" is omitted from zNum.)  This
    ** parameter is needed to determine a boundary case.  A string
    ** of "9223373036854775808" returns false if negFlag is false or true
    ** if negFlag is true.
    **
    ** Leading zeros are ignored.
    */

        public static bool Sqlite3FitsIn64Bits(string zNum, bool negFlag)
        {
            Int64 pNum;
            Debug.Assert(zNum[0] >= '0' && zNum[0] <= '9'); /* zNum is an unsigned number */
            bool result = negFlag ? Int64.TryParse("-" + zNum, out pNum) : Int64.TryParse(zNum, out pNum);
            // if ( result && negFlag && pNum == Int64.MaxValue  ) result = false;
            return result;
            //int i;
            //int neg = 0;
            //if (negFlag != 0) neg = 1 - neg;
            //while (*zNum == '0')
            //{
            //  zNum++;   /* Skip leading zeros.  Ticket #2454 */
            //}
            //for (i = 0;  zNum[i]; i++){ assert( zNum[i]>='0' && zNum[i]<='9' ); }
            //UnitTest.TestCase(i == 18);
            //UnitTest.TestCase(i == 19);
            //UnitTest.TestCase(i == 20);
            //if (i < 19)
            //{
            /* Guaranteed to fit if less than 19 digits */
            //  return 1;
            //}
            //else if (i > 19)
            //{
            /* Guaranteed to be too big if greater than 19 digits */
            //  return 0;
            //}
            //else
            //{
            /* Compare against 2^63. */
            //  if (Compare2pow63(new string(zNum)) < neg) return 1; else return 0;
            //}
        }

        /*
    ** If zNum represents an integer that will fit in 32-bits, then set
    ** pValue to that integer and return true.  Otherwise return false.
    **
    ** Any non-numeric characters that following zNum are ignored.
    ** This is different from Sqlite3Atoi64() which requires the
    ** input number to be zero-terminated.
    */

        public static bool Sqlite3GetInt32(string zNum, ref int pValue)
        {
            return Sqlite3GetInt32(zNum, 0, ref pValue);
        }

        public static bool Sqlite3GetInt32(string zNum, int iZnum, ref int pValue)
        {
            long v = 0;
            int i, c;
            int neg = 0;
            if (zNum[iZnum] == '-')
            {
                neg = 1;
                iZnum++;
            }
            else if (zNum[iZnum] == '+')
            {
                iZnum++;
            }
            while (iZnum < zNum.Length && zNum[iZnum] == '0') iZnum++;
            for (i = 0; i < 11 && i + iZnum < zNum.Length && (c = zNum[iZnum + i] - '0') >= 0 && c <= 9; i++)
            {
                v = v * 10 + c;
            }

            /* The longest decimal representation of a 32 bit integer is 10 digits:
      **
      **             1234567890
      **     2^31 . 2147483648
      */
            UnitTest.TestCase(i == 10);
            if (i > 10)
            {
                return false;
            }
            UnitTest.TestCase(v - neg == 2147483647);
            if (v - neg > 2147483647)
            {
                return false;
            }
            if (neg != 0)
            {
                v = -v;
            }
            pValue = (int)v;
            return true;
        }

        /*
    ** The variable-length integer encoding is as follows:
    **
    ** KEY:
    **         A = 0xxxxxxx    7 bits of data and one flag bit
    **         B = 1xxxxxxx    7 bits of data and one flag bit
    **         C = xxxxxxxx    8 bits of data
    **
    **  7 bits - A
    ** 14 bits - BA
    ** 21 bits - BBA
    ** 28 bits - BBBA
    ** 35 bits - BBBBA
    ** 42 bits - BBBBBA
    ** 49 bits - BBBBBBA
    ** 56 bits - BBBBBBBA
    ** 64 bits - BBBBBBBBC
    */

        /*
    ** Write a 64-bit variable-length integer to memory starting at p[0].
    ** The length of data write will be between 1 and 9 bytes.  The number
    ** of bytes written is returned.
    **
    ** A variable-length integer consists of the lower 7 bits of each byte
    ** for all bytes that have the 8th bit set and one byte with the 8th
    ** bit clear.  Except, if we get to the 9th byte, it stores the full
    ** 8 bits and is the last byte.
    */

        public static int GetVarint(byte[] p, ref uint v)
        {
            v = p[0];
            if (v <= 0x7F) return 1;
            ulong u64_v = 0;
            int result = Sqlite3GetVarint(p, 0, ref u64_v);
            v = (uint)u64_v;
            return result;
        }

        public static int GetVarint(byte[] p, int offset, ref uint v)
        {
            v = p[offset + 0];
            if (v <= 0x7F) return 1;
            ulong u64_v = 0;
            int result = Sqlite3GetVarint(p, offset, ref u64_v);
            v = (uint)u64_v;
            return result;
        }

        public static int GetVarint(byte[] p, int offset, ref int v)
        {
            v = p[offset + 0];
            if (v <= 0x7F) return 1;
            ulong u64_v = 0;
            int result = Sqlite3GetVarint(p, offset, ref u64_v);
            v = (int)u64_v;
            return result;
        }

        public static int GetVarint(byte[] p, int offset, ref long v)
        {
            v = offset >= p.Length ? 0 : p[offset + 0];
            if (v <= 0x7F) return 1;
            if (offset + 1 >= p.Length)
            {
                v = 65535;
                return 2;
            }
            else
            {
                ulong u64_v = 0;
                int result = Sqlite3GetVarint(p, offset, ref u64_v);
                v = (long)u64_v;
                return result;
            }
        }

        public static int GetVarint(byte[] p, int offset, ref ulong v)
        {
            v = p[offset + 0];
            if (v <= 0x7F) return 1;
            int result = Sqlite3GetVarint(p, offset, ref v);
            return result;
        }

        public static int GetVarint32(byte[] p, ref uint v)
        {
            //(*B=*(A))<=0x7f?1:Sqlite3GetVarint32(A,B))
            v = p[0];
            if (v <= 0x7F) return 1;
            return Sqlite3GetVarint32(p, 0, ref v);
        }

        private static readonly byte[] pByte4 = new byte[4];

        public static int GetVarint32(string s, uint offset, ref int v)
        {
            //(*B=*(A))<=0x7f?1:Sqlite3GetVarint32(A,B))
            v = s[(int)offset];
            if (v <= 0x7F) return 1;
            pByte4[0] = (byte)s[(int)offset + 0];
            pByte4[1] = (byte)s[(int)offset + 1];
            pByte4[2] = (byte)s[(int)offset + 2];
            pByte4[3] = (byte)s[(int)offset + 3];
            uint u32_v = 0;
            int result = Sqlite3GetVarint32(pByte4, 0, ref u32_v);
            v = (int)u32_v;
            return Sqlite3GetVarint32(pByte4, 0, ref v);
        }

        public static int GetVarint32(string s, uint offset, ref uint v)
        {
            //(*B=*(A))<=0x7f?1:Sqlite3GetVarint32(A,B))
            v = s[(int)offset];
            if (v <= 0x7F) return 1;
            pByte4[0] = (byte)s[(int)offset + 0];
            pByte4[1] = (byte)s[(int)offset + 1];
            pByte4[2] = (byte)s[(int)offset + 2];
            pByte4[3] = (byte)s[(int)offset + 3];
            return Sqlite3GetVarint32(pByte4, 0, ref v);
        }

        public static int GetVarint32(byte[] p, uint offset, ref uint v)
        {
            //(*B=*(A))<=0x7f?1:Sqlite3GetVarint32(A,B))
            v = p[offset];
            if (v <= 0x7F) return 1;
            return Sqlite3GetVarint32(p, (int)offset, ref v);
        }

        public static int GetVarint32(byte[] p, int offset, ref uint v)
        {
            //(*B=*(A))<=0x7f?1:Sqlite3GetVarint32(A,B))
            v = offset >= p.Length ? 0 : (uint)p[offset];
            if (v <= 0x7F) return 1;
            return Sqlite3GetVarint32(p, offset, ref v);
        }

        public static int GetVarint32(byte[] p, int offset, ref int v)
        {
            //(*B=*(A))<=0x7f?1:Sqlite3GetVarint32(A,B))
            v = p[offset + 0];
            if (v <= 0x7F) return 1;
            uint u32_v = 0;
            int result = Sqlite3GetVarint32(p, offset, ref u32_v);
            v = (int)u32_v;
            return result;
        }

        public static int PutVarint(byte[] p, int offset, int v)
        {
            return PutVarint(p, offset, (ulong)v);
        }

        public static int PutVarint(byte[] p, int offset, ulong v)
        {
            return Sqlite3PutVarint(p, offset, v);
        }

        public static int Sqlite3PutVarint(byte[] p, int offset, int v)
        {
            return Sqlite3PutVarint(p, offset, (ulong)v);
        }

        private static readonly byte[] bufByte10 = new byte[10];

        public static int Sqlite3PutVarint(byte[] p, int offset, ulong v)
        {
            int i, j, n;
            if ((v & (((ulong)0xff000000) << 32)) != 0)
            {
                p[offset + 8] = (byte)v;
                v >>= 8;
                for (i = 7; i >= 0; i--)
                {
                    p[offset + i] = (byte)((v & 0x7f) | 0x80);
                    v >>= 7;
                }
                return 9;
            }
            n = 0;
            do
            {
                bufByte10[n++] = (byte)((v & 0x7f) | 0x80);
                v >>= 7;
            } while (v != 0);
            bufByte10[0] &= 0x7f;
            Debug.Assert(n <= 9);
            for (i = 0, j = n - 1; j >= 0; j--, i++)
            {
                p[offset + i] = bufByte10[j];
            }
            return n;
        }

        /*
    ** This routine is a faster version of Sqlite3PutVarint() that only
    ** works for 32-bit positive integers and which is optimized for
    ** the common case of small integers.
    */

        public static int PutVarint32(byte[] p, int offset, int v)
        {
#if !putVarint32
            if ((v & ~0x7f) == 0)
            {
                p[offset] = (byte)v;
                return 1;
            }
#endif
            if ((v & ~0x3fff) == 0)
            {
                p[offset] = (byte)((v >> 7) | 0x80);
                p[offset + 1] = (byte)(v & 0x7f);
                return 2;
            }
            return Sqlite3PutVarint(p, offset, v);
        }

        public static int PutVarint32(byte[] p, int v)
        {
            if ((v & ~0x7f) == 0)
            {
                p[0] = (byte)v;
                return 1;
            }
            else if ((v & ~0x3fff) == 0)
            {
                p[0] = (byte)((v >> 7) | 0x80);
                p[1] = (byte)(v & 0x7f);
                return 2;
            }
            else
            {
                return Sqlite3PutVarint(p, 0, v);
            }
        }

        /*
    ** Bitmasks used by Sqlite3GetVarint().  These precomputed constants
    ** are defined here rather than simply putting the constant expressions
    ** inline in order to work around bugs in the RVT compiler.
    **
    ** SLOT_2_0     A mask for  (0x7f<<14) | 0x7f
    **
    ** SLOT_4_2_0   A mask for  (0x7f<<28) | SLOT_2_0
    */
        private const int SLOT_2_0 = 0x001fc07f; //#define SLOT_2_0     0x001fc07f
        private const uint SLOT_4_2_0 = 0xf01fc07f; //#define SLOT_4_2_0   0xf01fc07f

        /*
    ** Read a 64-bit variable-length integer from memory starting at p[0].
    ** Return the number of bytes read.  The value is stored in *v.
    */

        private static byte Sqlite3GetVarint(byte[] p, int offset, ref ulong v)
        {
            uint a, b, s;

            a = p[offset + 0];
            /* a: p0 (unmasked) */
            if (0 == (a & 0x80))
            {
                v = a;
                return 1;
            }

            //p++;
            b = p[offset + 1];
            /* b: p1 (unmasked) */
            if (0 == (b & 0x80))
            {
                a &= 0x7f;
                a = a << 7;
                a |= b;
                v = a;
                return 2;
            }

            /* Verify that constants are precomputed correctly */
            Debug.Assert(SLOT_2_0 == ((0x7f << 14) | (0x7f)));
            Debug.Assert(SLOT_4_2_0 == ((0xfU << 28) | (0x7f << 14) | (0x7f)));
            //p++;
            a = a << 14;
            a |= p[offset + 2];
            /* a: p0<<14 | p2 (unmasked) */
            if (0 == (a & 0x80))
            {
                a &= SLOT_2_0;
                b &= 0x7f;
                b = b << 7;
                a |= b;
                v = a;
                return 3;
            }

            /* CSE1 from below */
            a &= SLOT_2_0;
            //p++;
            b = b << 14;
            b |= p[offset + 3];
            /* b: p1<<14 | p3 (unmasked) */
            if (0 == (b & 0x80))
            {
                b &= SLOT_2_0;
                /* moved CSE1 up */
                /* a &= (0x7f<<14)|(0x7f); */
                a = a << 7;
                a |= b;
                v = a;
                return 4;
            }

            /* a: p0<<14 | p2 (masked) */
            /* b: p1<<14 | p3 (unmasked) */
            /* 1:save off p0<<21 | p1<<14 | p2<<7 | p3 (masked) */
            /* moved CSE1 up */
            /* a &= (0x7f<<14)|(0x7f); */
            b &= SLOT_2_0;
            s = a;
            /* s: p0<<14 | p2 (masked) */

            //p++;
            a = a << 14;
            a |= p[offset + 4];
            /* a: p0<<28 | p2<<14 | p4 (unmasked) */
            if (0 == (a & 0x80))
            {
                /* we can skip these cause they were (effectively) done above in calc'ing s */
                /* a &= (0x1f<<28)|(0x7f<<14)|(0x7f); */
                /* b &= (0x7f<<14)|(0x7f); */
                b = b << 7;
                a |= b;
                s = s >> 18;
                v = ((ulong)s) << 32 | a;
                return 5;
            }

            /* 2:save off p0<<21 | p1<<14 | p2<<7 | p3 (masked) */
            s = s << 7;
            s |= b;
            /* s: p0<<21 | p1<<14 | p2<<7 | p3 (masked) */

            //p++;
            b = b << 14;
            b |= p[offset + 5];
            /* b: p1<<28 | p3<<14 | p5 (unmasked) */
            if (0 == (b & 0x80))
            {
                /* we can skip this cause it was (effectively) done above in calc'ing s */
                /* b &= (0x1f<<28)|(0x7f<<14)|(0x7f); */
                a &= SLOT_2_0;
                a = a << 7;
                a |= b;
                s = s >> 18;
                v = ((ulong)s) << 32 | a;
                return 6;
            }

            //p++;
            a = a << 14;
            a |= p[offset + 6];
            /* a: p2<<28 | p4<<14 | p6 (unmasked) */
            if (0 == (a & 0x80))
            {
                a &= SLOT_4_2_0;
                b &= SLOT_2_0;
                b = b << 7;
                a |= b;
                s = s >> 11;
                v = ((ulong)s) << 32 | a;
                return 7;
            }

            /* CSE2 from below */
            a &= SLOT_2_0;
            //p++;
            b = b << 14;
            b |= p[offset + 7];
            /* b: p3<<28 | p5<<14 | p7 (unmasked) */
            if (0 == (b & 0x80))
            {
                b &= SLOT_4_2_0;
                /* moved CSE2 up */
                /* a &= (0x7f<<14)|(0x7f); */
                a = a << 7;
                a |= b;
                s = s >> 4;
                v = ((ulong)s) << 32 | a;
                return 8;
            }

            //p++;
            a = a << 15;
            a |= p[offset + 8];
            /* a: p4<<29 | p6<<15 | p8 (unmasked) */

            /* moved CSE2 up */
            /* a &= (0x7f<<29)|(0x7f<<15)|(0xff); */
            b &= SLOT_2_0;
            b = b << 8;
            a |= b;

            s = s << 4;
            b = p[offset + 4];
            b &= 0x7f;
            b = b >> 3;
            s |= b;

            v = ((ulong)s) << 32 | a;

            return 9;
        }


        /*
    ** Read a 32-bit variable-length integer from memory starting at p[0].
    ** Return the number of bytes read.  The value is stored in *v.
    **
    ** If the varint stored in p[0] is larger than can fit in a 32-bit unsigned
    ** integer, then set *v to 0xffffffff.
    **
    ** A MACRO version, GetVarint32, is provided which inlines the
    ** single-byte case.  All code should use the MACRO version as
    ** this function assumes the single-byte case has already been handled.
    */

        public static byte Sqlite3GetVarint32(byte[] p, ref int v)
        {
            uint u32_v = 0;
            byte result = Sqlite3GetVarint32(p, 0, ref u32_v);
            v = (int)u32_v;
            return result;
        }

        public static byte Sqlite3GetVarint32(byte[] p, int offset, ref int v)
        {
            uint u32_v = 0;
            byte result = Sqlite3GetVarint32(p, offset, ref u32_v);
            v = (int)u32_v;
            return result;
        }

        public static byte Sqlite3GetVarint32(byte[] p, ref uint v)
        {
            return Sqlite3GetVarint32(p, 0, ref v);
        }

        private static byte Sqlite3GetVarint32(byte[] p, int offset, ref uint v)
        {
            uint a, b;

            /* The 1-byte case.  Overwhelmingly the most common.  Handled inline
      ** by the getVarin32() macro */
            a = p[offset + 0];
            /* a: p0 (unmasked) */
            //#if GetVarint32
            //  if ( 0==( a&0x80))
            //  {
            /* Values between 0 and 127 */
            //    v = a;
            //    return 1;
            //  }
            //#endif

            /* The 2-byte case */
            //p++;
            b = p[offset + 1];
            /* b: p1 (unmasked) */
            if (0 == (b & 0x80))
            {
                /* Values between 128 and 16383 */
                a &= 0x7f;
                a = a << 7;
                v = a | b;
                return 2;
            }

            /* The 3-byte case */
            //p++;
            a = a << 14;
            a |= p[offset + 2];
            /* a: p0<<14 | p2 (unmasked) */
            if (0 == (a & 0x80))
            {
                /* Values between 16384 and 2097151 */
                a &= (0x7f << 14) | (0x7f);
                b &= 0x7f;
                b = b << 7;
                v = a | b;
                return 3;
            }

            /* A 32-bit varint is used to store size information in btrees.
      ** Objects are rarely larger than 2MiB limit of a 3-byte varint.
      ** A 3-byte varint is sufficient, for example, to record the size
      ** of a 1048569-byte BLOB or string.
      **
      ** We only unroll the first 1-, 2-, and 3- byte cases.  The very
      ** rare larger cases can be handled by the slower 64-bit varint
      ** routine.
      */
#if TRUE
            {
                ulong v64 = 0;
                byte n;

                //p -= 2;
                n = Sqlite3GetVarint(p, offset, ref v64);
                Debug.Assert(n > 3 && n <= 9);
                if ((v64 & Const.SQLITE_MAX_U32) != v64)
                {
                    v = 0xffffffff;
                }
                else
                {
                    v = (uint)v64;
                }
                return n;
            }
#else
/* For following code (kept for historical record only) shows an
** unrolling for the 3- and 4-byte varint cases.  This code is
** slightly faster, but it is also larger and much harder to test.
*/
//p++;
b = b << 14;
b |= p[offset + 3];
/* b: p1<<14 | p3 (unmasked) */
if ( 0 == ( b & 0x80 ) )
{
/* Values between 2097152 and 268435455 */
b &= ( 0x7f << 14 ) | ( 0x7f );
a &= ( 0x7f << 14 ) | ( 0x7f );
a = a << 7;
v = a | b;
return 4;
}

//p++;
a = a << 14;
a |= p[offset + 4];
/* a: p0<<28 | p2<<14 | p4 (unmasked) */
if ( 0 == ( a & 0x80 ) )
{
/* Values  between 268435456 and 34359738367 */
a &= SLOT_2_0;
b &= SLOT_4_2_0;
b = b << 7;
v = a | b;
return 5;
}

/* We can only reach this point when reading a corrupt database
** file.  In that case we are not in any hurry.  Use the (relatively
** slow) general-purpose Sqlite3GetVarint() routine to extract the
** value. */
{
ulong v64 = 0;
int n;

//p -= 4;
n = Sqlite3GetVarint( p, offset, ref v64 );
Debug.Assert( n > 5 && n <= 9 );
v = (uint)v64;
return n;
}
#endif
        }


        /*
    ** Return the number of bytes that will be needed to store the given
    ** 64-bit integer.
    */

        public static int Sqlite3VarintLen(ulong v)
        {
            int i = 0;
            do
            {
                i++;
                v >>= 7;
            } while (v != 0 && ALWAYS(i < 9));
            return i;
        }
        private static bool ALWAYS(bool X)//zy copy this function
        {
            return X;
        }

        /*
    ** Read or write a four-byte big-endian integer value.
    */

        public static uint Sqlite3Get4byte(byte[] p, int p_offset, int offset)
        {
            offset += p_offset;
            return (offset + 3 > p.Length)
                       ? 0
                       : (uint)((p[0 + offset] << 24) | (p[1 + offset] << 16) | (p[2 + offset] << 8) | p[3 + offset]);
        }

        public static uint Sqlite3Get4byte(byte[] p, int offset)
        {
            return (offset + 3 > p.Length)
                       ? 0
                       : (uint)((p[0 + offset] << 24) | (p[1 + offset] << 16) | (p[2 + offset] << 8) | p[3 + offset]);
        }

        public static uint Sqlite3Get4byte(byte[] p, uint offset)
        {
            return (offset + 3 > p.Length)
                       ? 0
                       : (uint)((p[0 + offset] << 24) | (p[1 + offset] << 16) | (p[2 + offset] << 8) | p[3 + offset]);
        }

        public static uint Sqlite3Get4byte(byte[] p)
        {
            return (uint)((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]);
        }

        public static void Sqlite3Put4byte(byte[] p, int v)
        {
            p[0] = (byte)(v >> 24 & 0xFF);
            p[1] = (byte)(v >> 16 & 0xFF);
            p[2] = (byte)(v >> 8 & 0xFF);
            p[3] = (byte)(v & 0xFF);
        }

        public static void Sqlite3Put4byte(byte[] p, int offset, int v)
        {
            p[0 + offset] = (byte)(v >> 24 & 0xFF);
            p[1 + offset] = (byte)(v >> 16 & 0xFF);
            p[2 + offset] = (byte)(v >> 8 & 0xFF);
            p[3 + offset] = (byte)(v & 0xFF);
        }

        public static void Sqlite3Put4byte(byte[] p, uint offset, uint v)
        {
            p[0 + offset] = (byte)(v >> 24 & 0xFF);
            p[1 + offset] = (byte)(v >> 16 & 0xFF);
            p[2 + offset] = (byte)(v >> 8 & 0xFF);
            p[3 + offset] = (byte)(v & 0xFF);
        }

        public static void Sqlite3Put4byte(byte[] p, int offset, ulong v)
        {
            p[0 + offset] = (byte)(v >> 24 & 0xFF);
            p[1 + offset] = (byte)(v >> 16 & 0xFF);
            p[2 + offset] = (byte)(v >> 8 & 0xFF);
            p[3 + offset] = (byte)(v & 0xFF);
        }

        public static void Sqlite3Put4byte(byte[] p, ulong v)
        {
            p[0] = (byte)(v >> 24 & 0xFF);
            p[1] = (byte)(v >> 16 & 0xFF);
            p[2] = (byte)(v >> 8 & 0xFF);
            p[3] = (byte)(v & 0xFF);
        }


#if !SQLITE_OMIT_BLOB_LITERAL || SQLITE_HAS_CODEC
        /*
** Translate a single byte of Hex into an integer.
** This routine only works if h really is a valid hexadecimal
** character:  0..9a..fA..F
*/

        private static int HexToInt(int h)
        {
            Debug.Assert((h >= '0' && h <= '9') || (h >= 'a' && h <= 'f') || (h >= 'A' && h <= 'F'));
#if SQLITE_ASCII
            h += 9 * (1 & (h >> 6));
#endif
#if SQLITE_EBCDIC
h += 9*(1&~(h>>4));
#endif
            return h & 0xf;
        }
#endif
        // * !SQLITE_OMIT_BLOB_LITERAL || SQLITE_HAS_CODEC */

#if !SQLITE_OMIT_BLOB_LITERAL || SQLITE_HAS_CODEC
        /*
** Convert a BLOB literal of the form "x'hhhhhh'" into its binary
** value.  Return a pointer to its binary value.  Space to hold the
** binary value has been obtained from malloc and must be freed by
** the calling routine.
*/

        public static byte[] Sqlite3HexToBlob(sqlite3 db, string z, int n)
        {
            StringBuilder zBlob;
            int i;

            zBlob = new StringBuilder(n / 2 + 1); // (char*)sqlite3DbMallocRaw(db, n / 2 + 1);
            n--;
            if (zBlob != null)
            {
                for (i = 0; i < n; i += 2)
                {
                    zBlob.Append(Convert.ToChar((HexToInt(z[i]) << 4) | HexToInt(z[i + 1])));
                }
                //zBlob[i / 2] = '\0'; ;
            }
            return Encoding.UTF8.GetBytes(zBlob.ToString());
        }
#endif
        // * !SQLITE_OMIT_BLOB_LITERAL || SQLITE_HAS_CODEC */


        /*
** Log an error that is an API call on a connection pointer that should
** not have been used.  The "type" of connection pointer is given as the
** argument.  The zType is a word like "NULL" or "closed" or "invalid".
*/

        public static void logBadConnection(string zType)
        {
            Print.Sqlite3_log(StatusCode.SQLITE_MISUSE,
                        "API call with %s database connection pointer",
                        zType
                );
        }

        /*
    ** Check to make sure we have a valid db pointer.  This test is not
    ** foolproof but it does provide some measure of protection against
    ** misuse of the interface such as passing in db pointers that are
    ** NULL or which have been previously closed.  If this routine returns
    ** 1 it means that the db pointer is valid and 0 if it should not be
    ** dereferenced for any reason.  The calling function should invoke
    ** StatusCode.SQLITE_MISUSE immediately.
    **
    ** Sqlite3SafetyCheckOk() requires that the db pointer be valid for
    ** use.  Sqlite3SafetyCheckSickOrOk() allows a db pointer that failed to
    ** open properly and is not fit for general use but which can be
    ** used as an argument to sqlite3_errmsg() or sqlite3_close().
    */

        public static bool Sqlite3SafetyCheckOk(sqlite3 db)
        {
            uint magic;
            if (db == null)
            {
                logBadConnection("NULL");
                return false;
            }
            magic = db.magic;
            if (magic != Const.SQLITE_MAGIC_OPEN)
            {
                if (Sqlite3SafetyCheckSickOrOk(db))
                {
                    UnitTest.TestCase(Global.Config.xLog != null);
                    logBadConnection("unopened");
                }
                return false;
            }
            else
            {
                return true;
            }
        }

        public static bool Sqlite3SafetyCheckSickOrOk(sqlite3 db)
        {
            uint magic;
            magic = db.magic;
            if (magic != Const.SQLITE_MAGIC_SICK &&
                magic != Const.SQLITE_MAGIC_OPEN &&
                magic != Const.SQLITE_MAGIC_BUSY)
            {
                UnitTest.TestCase(Global.Config.xLog != null);
                logBadConnection("invalid");
                return false;
            }
            else
            {
                return true;
            }
        }
    }
}
